﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;
using System.IO.Compression;
using System.Net;
using ESF.General;

#endregion


namespace ESF.Web
{
	public static class ModuleHandlerHelper
	{
		#region Constantes

		public const string GZIP = "gzip";
		public const string DEFLATE = "deflate";

		#endregion


		#region Verificacion AJAX

		public static bool IsAJAXRequest(HttpRequest pRequest)
		{
			return 
				(pRequest["X-Requested-With"] == "XMLHttpRequest")
				|| (pRequest["HTTP_X_MICROSOFTAJAX"] != null)
				|| ((pRequest.Headers != null) && 
					(pRequest.Headers["X-Requested-With"] == "XMLHttpRequest"						
						|| (pRequest.Headers["X-MicrosoftAjax"] != null))
				);
		}

		#endregion


		#region Ajuste de Cache

		public static bool GeneratedResponse_SetETagCacheIs304File(HttpContext pContext, string pFilename, string pExtraETagParams, int pMaxAgeDays, out FileInfo pFileInfo, out string pETag)
		{
			if (!File.Exists(pFilename))
			{
				pFileInfo = null;
				pETag = null;
				pContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
				pContext.Response.StatusDescription = string.Format("The file {0} was not found", Path.GetFileName(pFilename));
				return true;
			}

			pFileInfo = new FileInfo(pFilename);

			pETag = TextHelper.GetMD5Hash(pFilename + pFileInfo.LastWriteTime.ToString ("yyyyMMddHHmmss") + (string.IsNullOrEmpty(pExtraETagParams) ? string.Empty : pExtraETagParams));

			if (pContext.Request.Headers["If-None-Match"] == pETag)
			{
				pContext.Response.StatusCode = 304;
				pContext.Response.StatusDescription = "Not Modified";
				return true;
			}

			switch (pFileInfo.Extension.ToUpper())
			{
				case ".APPLICATION":
					pContext.Response.ContentType = "application/x-ms-application";
					break;

				case ".JS":
					pContext.Response.ContentType = "application/x-javascript";
					break;

				case ".CSS":
					pContext.Response.ContentType = "text/css";
					break;

				default:
					pContext.Response.ContentType = "application/octetstream";
					break;
			}

			if (pMaxAgeDays <= 0)
			{
				pContext.Response.Cache.SetExpires (pFileInfo.LastWriteTime);
				pContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
			}
			else
			{
				pContext.Response.Cache.SetExpires (pFileInfo.LastWriteTime.AddDays (pMaxAgeDays));
				pContext.Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
			}

			//pContext.Response.Cache.SetValidUntilExpires(true);

			pContext.Response.Cache.SetLastModified (DateTime.Now);
			pContext.Response.Cache.SetETag(pETag);

			return false;
		}

		#endregion


		#region Zip

		public static bool ShouldCompressPage(HttpContext pContext)
		{
			return
				!TextHelper.IsIn (Path.GetExtension (pContext.Request.PhysicalPath), ".APPLICATION", ".GIF", ".JPEG", ".JPG", ".BMP", ".TIFF")
				&& !(pContext.Request.UserAgent != null && pContext.Request.UserAgent.Contains("MSIE 6"))
				//&& !pContext.Request.Path.Contains("ScriptResource.axd")
				//&& (pContext.CurrentHandler is System.Web.UI.Page) // || app.Context.CurrentHandler is System.Web.Mvc.MvcHandler)
				//&& !IsAJAXRequest (pContext.Request)
				&& (pContext.Request.QueryString["_TSM_CombinedScripts_"] == null)
				&& (pContext.Request.QueryString["_TSM_HiddenField_"] == null);
		}


		public static void AddZipFilter(HttpContext pContext)
		{
			if (!ShouldCompressPage (pContext)) 
			{ 
				return; 
			}

			// prefer Deflate. It doesn't require checksums, and is therefore smaller and faster.
			if (IsEncodingAccepted(pContext, DEFLATE))
			{
				pContext.Response.Filter = new DeflateStream(pContext.Response.Filter, CompressionMode.Compress);
				
				AddESFDescriptionHeader (pContext, "Compressed");
				AddHeaderVaryByEncoding (pContext);
				AddHeaderEncoding(pContext, DEFLATE);
			}
			else if (IsEncodingAccepted(pContext, GZIP))
			{
				pContext.Response.Filter = new GZipStream(pContext.Response.Filter, CompressionMode.Compress);

				AddESFDescriptionHeader(pContext, "Compressed"); 
				AddHeaderVaryByEncoding(pContext); 
				AddHeaderEncoding(pContext, GZIP);
			}
		}


		public static void AddHeaderVaryByEncoding(HttpContext pContext)
		{
			AddHeaderVary (pContext, "Accept-Encoding");
		}


		public static void AddHeaderVary(HttpContext pContext, string pVaryValue)
		{
			pContext.Response.AppendHeader("Vary", pVaryValue);
		}
		 

		public static void AddHeaderEncoding(HttpContext pContext, string pEncoding)
		{
			pContext.Response.AppendHeader("Content-encoding", pEncoding);
		}


		public static bool IsEncodingAccepted(HttpContext pContext, string encoding)
		{
			bool ae = pContext.Request.Headers["Accept-encoding"] != null && 
				pContext.Request.Headers["Accept-encoding"].Contains(encoding);

			bool hae = pContext.Request.ServerVariables["HTTP_ACCEPT_ENCODING"] != null && 
				pContext.Request.ServerVariables["HTTP_ACCEPT_ENCODING"].Contains(encoding);

			return ae || hae;
		}

		#endregion


		#region Encabezados

		public static void AddESFDescriptionHeader (HttpContext pContext, string pDescription)
		{
			pContext.Response.AppendHeader ("ESFWebXDes", pDescription);
		}


		#endregion
	}
}
